const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
-const HOT_CORNER_ACTIVATION_TIMEOUT = 0.5;
const STARTUP_ANIMATION_TIME = 0.5;
const KEYBOARD_ANIMATION_TIME = 0.15;
const BACKGROUND_FADE_ANIMATION_TIME = 1.0;
this.monitors = [];
this.primaryMonitor = null;
this.primaryIndex = -1;
+ this.hotCorners = [];
+
this._keyboardIndex = -1;
- this._hotCorners = [];
this._leftPanelBarrier = null;
this._rightPanelBarrier = null;
this._trayBarrier = null;
_updateHotCorners: function() {
// destroy old hot corners
- for (let i = 0; i < this._hotCorners.length; i++)
- this._hotCorners[i].destroy();
- this._hotCorners = [];
+ for (let i = 0; i < this.hotCorners.length; i++)
+ this.hotCorners[i].destroy();
+ this.hotCorners = [];
// build new hot corners
for (let i = 0; i < this.monitors.length; i++) {
- if (i == this.primaryIndex)
- continue;
-
let monitor = this.monitors[i];
let cornerX = this._rtl ? monitor.x + monitor.width : monitor.x;
let cornerY = monitor.y;
- let haveTopLeftCorner = true;
+ if (i != this.primaryIndex) {
+ let haveTopLeftCorner = true;
- // Check if we have a top left (right for RTL) corner.
- // I.e. if there is no monitor directly above or to the left(right)
- let besideX = this._rtl ? monitor.x + 1 : cornerX - 1;
- let besideY = cornerY;
- let aboveX = cornerX;
- let aboveY = cornerY - 1;
+ // Check if we have a top left (right for RTL) corner.
+ // I.e. if there is no monitor directly above or to the left(right)
+ let besideX = this._rtl ? monitor.x + 1 : cornerX - 1;
+ let besideY = cornerY;
+ let aboveX = cornerX;
+ let aboveY = cornerY - 1;
- for (let j = 0; j < this.monitors.length; j++) {
- if (i == j)
- continue;
- let otherMonitor = this.monitors[j];
- if (besideX >= otherMonitor.x &&
- besideX < otherMonitor.x + otherMonitor.width &&
- besideY >= otherMonitor.y &&
- besideY < otherMonitor.y + otherMonitor.height) {
- haveTopLeftCorner = false;
- break;
- }
- if (aboveX >= otherMonitor.x &&
- aboveX < otherMonitor.x + otherMonitor.width &&
- aboveY >= otherMonitor.y &&
- aboveY < otherMonitor.y + otherMonitor.height) {
- haveTopLeftCorner = false;
- break;
+ for (let j = 0; j < this.monitors.length; j++) {
+ if (i == j)
+ continue;
+ let otherMonitor = this.monitors[j];
+ if (besideX >= otherMonitor.x &&
+ besideX < otherMonitor.x + otherMonitor.width &&
+ besideY >= otherMonitor.y &&
+ besideY < otherMonitor.y + otherMonitor.height) {
+ haveTopLeftCorner = false;
+ break;
+ }
+ if (aboveX >= otherMonitor.x &&
+ aboveX < otherMonitor.x + otherMonitor.width &&
+ aboveY >= otherMonitor.y &&
+ aboveY < otherMonitor.y + otherMonitor.height) {
+ haveTopLeftCorner = false;
+ break;
+ }
}
- }
- if (!haveTopLeftCorner)
- continue;
+ if (!haveTopLeftCorner)
+ continue;
+ }
let corner = new HotCorner(this);
- this._hotCorners.push(corner);
+ this.hotCorners.push(corner);
corner.actor.set_position(cornerX, cornerY);
this.addChrome(corner.actor);
}
+
+ this.emit('hot-corners-changed');
},
_createBackground: function(monitorIndex) {
},
_panelBoxChanged: function() {
- this.emit('panel-box-changed');
this._updatePanelBarriers();
},
if (!Main.sessionMode.isGreeter)
this._createSecondaryBackgrounds();
- this.emit('panel-box-changed');
-
this._queueUpdateRegions();
this.emit('startup-complete');
this._corner.set_position(0, 0);
}
- this._activationTime = 0;
-
this.actor.connect('leave-event',
Lang.bind(this, this._onEnvironsLeft));
- // Clicking on the hot corner environs should result in the
- // same behavior as clicking on the hot corner.
- this.actor.connect('button-release-event',
- Lang.bind(this, this._onCornerClicked));
-
- // In addition to being triggered by the mouse enter event,
- // the hot corner can be triggered by clicking on it. This is
- // useful if the user wants to undo the effect of triggering
- // the hot corner once in the hot corner.
this._corner.connect('enter-event',
Lang.bind(this, this._onCornerEntered));
- this._corner.connect('button-release-event',
- Lang.bind(this, this._onCornerClicked));
this._corner.connect('leave-event',
Lang.bind(this, this._onCornerLeft));
_onCornerEntered : function() {
if (!this._entered) {
this._entered = true;
- if (!Main.overview.animationInProgress) {
- this._activationTime = Date.now() / 1000;
-
+ if (Main.overview.shouldToggleByCornerOrButton()) {
this.rippleAnimation();
Main.overview.toggle();
}
return false;
},
- _onCornerClicked : function() {
- if (this.shouldToggleOverviewOnClick())
- Main.overview.toggle();
- return true;
- },
-
_onCornerLeft : function(actor, event) {
if (event.get_related() != this.actor)
this._entered = false;
if (event.get_related() != this._corner)
this._entered = false;
return false;
- },
-
- // Checks if the Activities button is currently sensitive to
- // clicks. The first call to this function within the
- // HOT_CORNER_ACTIVATION_TIMEOUT time of the hot corner being
- // triggered will return false. This avoids opening and closing
- // the overview if the user both triggered the hot corner and
- // clicked the Activities button.
- shouldToggleOverviewOnClick: function() {
- if (Main.overview.animationInProgress)
- return false;
- if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > HOT_CORNER_ACTIVATION_TIMEOUT)
- return true;
- return false;
}
});
else
screenShield = new ScreenShield.ScreenShieldFallback();
- // The message tray relies on being constructed
- // after the panel.
panel = new Panel.Panel();
messageTray = new MessageTray.MessageTray();
keyboard = new Keyboard.Keyboard();
Main.layoutManager.trackChrome(this._closeButton);
Main.layoutManager.connect('primary-fullscreen-changed', Lang.bind(this, this._onFullscreenChanged));
+ Main.layoutManager.connect('hot-corners-changed', Lang.bind(this, this._hotCornersChanged));
// If the overview shows or hides while we're in
// the message tray, revert back to normal mode.
Main.overview.connect('showing', Lang.bind(this, this._escapeTray));
Main.overview.connect('hiding', Lang.bind(this, this._escapeTray));
- // Track if we've added the activities button
- this._activitiesButtonAdded = false;
Main.sessionMode.connect('updated', Lang.bind(this, this._sessionUpdated));
Main.wm.addKeybinding('toggle-message-tray',
this._trayDwellTimeoutId = 0;
this._setupTrayDwellIfNeeded();
this._sessionUpdated();
+ this._hotCornersChanged();
this._noMessages = new St.Label({ text: _("No Messages"),
style_class: 'no-messages-label',
},
_sessionUpdated: function() {
- if (!this._activitiesButtonAdded && Main.panel.statusArea.activities) {
- this._activitiesButtonAdded = true;
- this._grabHelper.addActor(Main.panel.statusArea.activities.hotCorner.actor);
- }
-
if ((Main.sessionMode.isLocked || Main.sessionMode.isGreeter) && this._inCtrlAltTab) {
Main.ctrlAltTabManager.removeGroup(this._summary);
this._inCtrlAltTab = false;
this._updateState();
},
+ _hotCornersChanged: function() {
+ let primary = Main.layoutManager.primaryIndex;
+ let corner = Main.layoutManager.hotCorners[primary];
+ if (corner && corner.actor)
+ this._grabHelper.addActor(corner.actor);
+ },
+
_onTrayHoverChanged: function() {
if (this.actor.hover) {
// No dwell inside notifications at the bottom of the screen
const DND_WINDOW_SWITCH_TIMEOUT = 1250;
+const OVERVIEW_ACTIVATION_TIMEOUT = 0.5;
+
const ShellInfo = new Lang.Class({
Name: 'ShellInfo',
this._backgroundGroup.hide();
this._bgManagers = [];
+ this._activationTime = 0;
+
this.visible = false; // animating to overview, in overview, animating out
this._shown = false; // show() and not hide()
this._shownTemporarily = false; // showTemporarily() and not hideTemporarily()
this.visible = true;
this.animationInProgress = true;
this.visibleTarget = true;
+ this._activationTime = Date.now() / 1000;
// All the the actors in the window group are completely obscured,
// hiding the group holding them while the Overview is displayed greatly
this.show();
},
+ // Checks if the Activities button is currently sensitive to
+ // clicks. The first call to this function within the
+ // OVERVIEW_ACTIVATION_TIMEOUT time of the hot corner being
+ // triggered will return false. This avoids opening and closing
+ // the overview if the user both triggered the hot corner and
+ // clicked the Activities button.
+ shouldToggleByCornerOrButton: function() {
+ if (this.animationInProgress)
+ return false;
+ if (this._activationTime == 0 || Date.now() / 1000 - this._activationTime > OVERVIEW_ACTIVATION_TIMEOUT)
+ return true;
+ return false;
+ },
+
//// Private methods ////
_syncInputMode: function() {
const Config = imports.misc.config;
const CtrlAltTab = imports.ui.ctrlAltTab;
const DND = imports.ui.dnd;
-const Layout = imports.ui.layout;
const Overview = imports.ui.overview;
const PopupMenu = imports.ui.popupMenu;
const PanelMenu = imports.ui.panelMenu;
this.parent(0.0, null, true);
this.actor.accessible_role = Atk.Role.TOGGLE_BUTTON;
- let container = new Shell.GenericContainer();
- container.connect('get-preferred-width', Lang.bind(this, this._containerGetPreferredWidth));
- container.connect('get-preferred-height', Lang.bind(this, this._containerGetPreferredHeight));
- container.connect('allocate', Lang.bind(this, this._containerAllocate));
- this.actor.add_actor(container);
this.actor.name = 'panelActivities';
/* Translators: If there is no suitable word for "Activities"
in your language, you can use the word for "Overview". */
this._label = new St.Label({ text: _("Activities") });
- container.add_actor(this._label);
+ this.actor.add_actor(this._label);
this.actor.label_actor = this._label;
- this.hotCorner = new Layout.HotCorner(Main.layoutManager);
- container.add_actor(this.hotCorner.actor);
-
this.actor.connect('captured-event', Lang.bind(this, this._onCapturedEvent));
this.actor.connect_after('button-release-event', Lang.bind(this, this._onButtonRelease));
this.actor.connect_after('key-release-event', Lang.bind(this, this._onKeyRelease));
}));
this._xdndTimeOut = 0;
-
- // Since the hot corner uses stage coordinates, Clutter won't
- // queue relayouts for us when the panel moves. Queue a relayout
- // when that happens.
- Main.layoutManager.connect('panel-box-changed', Lang.bind(this, function() {
- container.queue_relayout();
- }));
- },
-
- _containerGetPreferredWidth: function(actor, forHeight, alloc) {
- [alloc.min_size, alloc.natural_size] = this._label.get_preferred_width(forHeight);
- },
-
- _containerGetPreferredHeight: function(actor, forWidth, alloc) {
- [alloc.min_size, alloc.natural_size] = this._label.get_preferred_height(forWidth);
- },
-
- _containerAllocate: function(actor, box, flags) {
- this._label.allocate(box, flags);
-
- // The hot corner needs to be outside any padding/alignment
- // that has been imposed on us
- let primary = Main.layoutManager.primaryMonitor;
- let hotBox = new Clutter.ActorBox();
- let ok, x, y;
- if (actor.get_text_direction() == Clutter.TextDirection.LTR) {
- [ok, x, y] = actor.transform_stage_point(primary.x, primary.y)
- } else {
- [ok, x, y] = actor.transform_stage_point(primary.x + primary.width, primary.y);
- // hotCorner.actor has northeast gravity, so we don't need
- // to adjust x for its width
- }
-
- hotBox.x1 = Math.round(x);
- hotBox.x2 = hotBox.x1 + this.hotCorner.actor.width;
- hotBox.y1 = Math.round(y);
- hotBox.y2 = hotBox.y1 + this.hotCorner.actor.height;
- this.hotCorner.actor.allocate(hotBox, flags);
},
handleDragOver: function(source, actor, x, y, time) {
_onCapturedEvent: function(actor, event) {
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
- if (!this.hotCorner.shouldToggleOverviewOnClick())
+ if (!Main.overview.shouldToggleByCornerOrButton())
return true;
}
return false;